﻿using Xejen.Ipc.Framework;
using Xejen.Ipc.Framework.Flows;
using Xejen.Ipc.Framework.Steps;
using Xejen.Ipc.Test.Steps;
using Xejen.Logger.NLog;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Xejen.Ipc.Test
{
    public partial class MainForm : Form
    {
        protected IFlow<Data> MainFlow;
        private CancellationTokenSource _cancellationTokenSource;

        public static MainForm Instance;
        public IFlow<Data> Unit7Flow;

        public MainForm()
        {
            InitializeComponent();

            Instance = this;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            IFlow<Data> childFlow1 = IpcHost.CreateHost(new IpcHostConfig { ScanIntervalThreshold = 2030 }, NLogManager.Instance()).CreateFlowWithFactory<Data>((factory) =>
            {
                return factory.NewControllerBuilder()
                        .Then(p => p.New<ChildUnit1>("子单元1"))
                        .Then(p => p.New<ChildUnit2>("子单元2"))
                        .Then(p => p.New<ChildUnit3>("子单元3"))
                        .Build("子流程");
            });
            Unit7Flow = childFlow1;

            var mainFlow = CreateFlow(new IpcHostConfig { ScanIntervalThreshold = 2030 }, (factory) =>
            {
                return factory.NewControllerBuilder()
                        .Then(p => p.New<Unit1>("单元1"))
                        .If(data => data.Value >= 10, (data) =>
                        {
                            Debug.WriteLine($"没有触发条件，因为值是{data.Value}");
                        }, p => p.New<Unit2>("单元2"))
                        .Then(p => p.New<Unit3>("单元3"))
                        .All(p => p.New<Unit4>("单元4"), p => p.New<Unit5>("单元5"))
                        .Any(p => p.New<Unit6>("单元6"), p => p.New<Unit7>("单元7"))
                        .Then(p => p.New<Unit8>("单元8"))
                        .Build("主流程");
            });
            MainFlow = mainFlow;
        }

        private IFlow<Data> CreateFlow(IpcHostConfig options, Func<IBuilderFactory<Data>, IFlow<Data>> func)
        {
            var flow = IpcHost.CreateHost(options, NLogManager.Instance()).CreateFlowWithFactory(func);
            flow.Started += (sender, args) => { Debug.WriteLine($"流程启动：{args.Flow.Id} : {args.Flow.Name}"); };
            flow.Paused += (sender, args) => { Debug.WriteLine($"流程暂停：{args.Flow.Id} : {args.Flow.Name}"); };
            flow.Resumed += (sender, args) => { Debug.WriteLine($"流程恢复：{args.Flow.Id} : {args.Flow.Name}"); };
            flow.Stopped += (sender, args) => { Debug.WriteLine($"流程停止：{args.Flow.Id} : {args.Flow.Name}"); };
            flow.CycleCompleted += (sender, args) =>
            {
                SetCycle(args.Flow.CycleExecutionTime);
            };
            flow.ScanIntervalExceeded += (sender, args) =>
            {
                Invoke(new Action(() =>
                {
                    MessageLabel.Text = "扫描周期过长提醒 " + Math.Ceiling(args.ScanInterval.TotalMilliseconds).ToString() + " ms，发生时间在：" + args.Flow.CycleEndTime.Value.ToString("yyyy-MM-dd HH:mm:ss:fff");
                }));
            };
            flow.Controllers.ForEach((controller) =>
            {
                controller.Steps.ForEach((step) =>
                {

                });
            });
            flow.Error += (sender, args) =>
            {
                Invoke(new Action(() =>
                {
                    ErrorTextBox.Text = args.Exception.StackTrace
                    + Environment.NewLine
                    + "----------------------" + DateTime.Now.ToString() + "-----------------------"
                    + Environment.NewLine
                    + ErrorTextBox.Text;
                }));
            };

            return flow;
        }

        /// <summary>
        /// 周期循环处理工作流程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            _cancellationTokenSource = new CancellationTokenSource();
            MainFlow.Start(_cancellationTokenSource.Token);
        }

        /// <summary>
        /// 暂停
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            MainFlow?.Pause();
        }

        /// <summary>
        /// 继续
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            MainFlow?.Resume();
        }

        /// <summary>
        /// 中止
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            MainFlow?.Stop();
        }

        /// <summary>
        /// 取消
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            _cancellationTokenSource?.Cancel();
        }

        /// <summary>
        /// 设置扫描周期
        /// </summary>
        /// <param name="ts"></param>
        public void SetCycle(TimeSpan? ts)
        {
            if (ts == null)
            {
                CycleLabel.Text = string.Empty;
                return;
            }

            if (InvokeRequired)
            {
                Invoke(new Action<TimeSpan?>(SetCycle), ts);
                return;
            }

            CycleLabel.Text = Math.Ceiling(ts.Value.TotalMilliseconds).ToString() + " ms";
        }

        /// <inheritdoc/>
        protected override void OnClosing(CancelEventArgs e)
        {
            MainFlow?.Stop();

            base.OnClosing(e);
        }
    }
}
